package com.jsx.hyyscript.module.importsystask.controller;

import com.alibaba.fastjson.JSON;
import com.jsx.hyyscript.common.domian.*;
import com.jsx.hyyscript.common.exception.HyyException;
import com.jsx.hyyscript.common.finalfiled.FinalStr;
import com.jsx.hyyscript.common.finalfiled.PermissionOperation;
import com.jsx.hyyscript.common.util.HttpsUtils;
import com.jsx.hyyscript.common.util.Mp4Util;
import com.jsx.hyyscript.common.util.ParseExcel;
import com.jsx.hyyscript.module.importsystask.entity.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.Logger;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.jsx.hyyscript.common.finalfiled.FinalInt.PUBLISH_TYPE_CONVERT;
import static com.jsx.hyyscript.common.finalfiled.FinalInt.PUBLISH_TYPE_SYSTEM_TASK;
import static com.jsx.hyyscript.common.finalfiled.FinalStr.WEB_TOKEN;
import static com.jsx.hyyscript.common.finalfiled.ResultCode.OK;

/**
 * @author zhuZhaoYang
 * @date 2021/9/3 11:01
 */
@RestController
@Validated
public class ImportSysTask {
    public static String WS = "http://localhost:8082/";
    public static ClassifyList classifyList;

    @PostMapping("/importSysTask")
    public RI importSysTask(@RequestParam("fileName") MultipartFile uploadFile) {
        if (uploadFile == null) {
            throw new HyyException(500, "上传的文件不能为空");
        }
        String name = uploadFile.getOriginalFilename();
        if (name == null || (!name.endsWith(FinalStr.EXCEL_TYPE_1) && !name.endsWith(FinalStr.EXCEL_TYPE_2))) {
            throw new HyyException(500, "不支持的文件类型,目前只支持 " + FinalStr.EXCEL_TYPE_1 + "," + FinalStr.EXCEL_TYPE_2);
        }
        File file = new File("c:\\xb", name);
        if (file.exists()) {
            boolean delete = file.delete();
            Logger.getLogger(this.getClass()).debug("删除文件 " + file.getAbsolutePath() + "             " + delete);
        }
        try {
            uploadFile.transferTo(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ParseExcel parseExcel = new ParseExcel(file.getAbsolutePath(), 18);
        List<String[]> strings = parseExcel.parseExcel();
        //验证表头
        checkExcelHead(strings);
        //获取数据字典
        classifyList = getClassifyList();
//        System.out.println(classifyList);
        //读取并检验数据合法性
        List<SysTaskHead> sysTasks = readAndCheck(strings);
        //上传视频并将任务导入
        uploadVideoAndAddSysTask(sysTasks);
        return new RS();
    }

    public void uploadVideoAndAddSysTask(List<SysTaskHead> sysTasks) {
        StringBuilder errorMsg = new StringBuilder();
        for (int i = 0; i < sysTasks.size(); i++) {
            String md5 = null;
            try {
                md5 = DigestUtils.md5Hex(new FileInputStream(sysTasks.get(i).getPath()));
            } catch (IOException e) {
                String msg = "第" + (i + 1) + "行视频有误，任务名称为:" + sysTasks.get(i).getTaskName() + "请检查视频路径或视频资源是否正确\n";
                errorMsg.append(msg);
            }
            PublishVideoDataPost publishVideoDataPost = new PublishVideoDataPost();
            publishVideoDataPost.setUuid(md5);
            publishVideoDataPost.setToken(WEB_TOKEN);
            publishVideoDataPost.setName(sysTasks.get(i).getTaskName());
            publishVideoDataPost.setTypeId(PUBLISH_TYPE_SYSTEM_TASK);
            publishVideoDataPost.setNeedStore(1);
            publishVideoDataPost.setNeedLive(0);
            PublishServerBackRSD returnData = publishVideoData(publishVideoDataPost);
            System.out.println("============================");
            System.out.println(returnData);
            if (returnData.getResultCode() != 200 && returnData.getResultCode() != 501 || returnData.getData() == null) {
                String msg = "第" + (i + 1) + "行视频请求上传时出错，任务名称为:" + sysTasks.get(i).getTaskName() + " 请检查视频路径或视频资源是否正确\n";
                errorMsg.append(msg);
                continue;
            }
            PublishServerBack publishServerBack = returnData.getData();
            if (returnData.getResultCode() != 501) {
                //501 文件已存在
                String postUrl = "http://" + publishServerBack.getSsInfo().getIp() + ":" + publishServerBack.getSsInfo().getPort() +
                        "/uploadVideo";
                try {
                    HttpsUtils.postFile(postUrl, "publishToken",
                            publishServerBack.getPublishToken(),
                            new File(sysTasks.get(i).getPath()));
                } catch (IOException e) {
                    String msg = "第" + (i + 1) + "行视频上传时出错，任务名称为:" + sysTasks.get(i).getTaskName() + " 请检查视频路径或视频资源是否正确\n";
                    errorMsg.append(msg);
                }
                RI ri = publishVideoDataEnd(publishServerBack.getPublishToken(), publishServerBack.getPublishId());
                if (ri == null || ri.getResultCode() != OK) {
                    String msg = "第" + (i + 1) + "行视频上传时出错，任务名称为:" + sysTasks.get(i).getTaskName() + " 请检查视频路径或视频资源是否正确\n";
                    errorMsg.append(msg);
                }
                //上传封面
                PublishImageData publishImageData = new PublishImageData();
                publishImageData.setPublishId(publishServerBack.getPublishId());
                publishImageData.setToken(WEB_TOKEN);
                publishImageData.setTypeId(PUBLISH_TYPE_CONVERT);
                PublishImageServerBackRSD imageReturnData = publishImageData(publishImageData);
                if (imageReturnData == null || imageReturnData.getResultCode() != 200) {
                    String msg = "第" + (i + 1) + "行视频请求上传封面时出错，任务名称为:" + sysTasks.get(i).getTaskName() + " 请检查视频路径或视频资源是否正确\n";
                    errorMsg.append(msg);
                    continue;
                }
                PublishImageServerBack publishImageServerBack = (PublishImageServerBack) imageReturnData.getData();
                File screenshot = null;
                try {
                    screenshot = Mp4Util.getScreenshot(sysTasks.get(i).getPath());
                } catch (Exception e) {
                    String msg = "第" + (i + 1) + "行视频获取封面时出错，任务名称为:" + sysTasks.get(i).getTaskName() + " 请检查视频路径或视频资源是否正确\n";
                    errorMsg.append(msg);
                }
                String imageUrl = "http://" + publishImageServerBack.getSsInfo().getIp() + ":" + publishImageServerBack.getSsInfo().getPort() +
                        "/uploadImage";
                try {
                    HttpsUtils.postFile(imageUrl, "imageToken",
                            publishImageServerBack.getImageToken(),
                            screenshot);
                } catch (IOException e) {
                    String msg = "第" + (i + 1) + "行视频上传封面时出错，任务名称为:" + sysTasks.get(i).getTaskName() + " 请检查视频路径或视频资源是否正确\n";
                    errorMsg.append(msg);
                }
                RI imageEnd = publishImageEnd(publishImageServerBack.getImageToken(), publishImageServerBack.getImageId());
                if (imageEnd == null || imageEnd.getResultCode() != OK) {
                    String msg = "第" + (i + 1) + "行视频上传封面时出错，任务名称为:" + sysTasks.get(i).getTaskName() + " 请检查视频路径或视频资源是否正确\n";
                    errorMsg.append(msg);
                }
            }
            //新增任务
            SystemTaskAdd systemTaskAdd = new SystemTaskAdd();
            systemTaskAdd.setTaskName(sysTasks.get(i).getTaskName());
            systemTaskAdd.setTaskMaterials(sysTasks.get(i).getTaskMaterials());
            systemTaskAdd.setTaskDes(sysTasks.get(i).getTaskDes());
            systemTaskAdd.setKeyExperience(sysTasks.get(i).getKeyExperience());
            systemTaskAdd.setKeyExperienceDes(sysTasks.get(i).getKeyExperienceDes());
            systemTaskAdd.setBehavioralHabit(sysTasks.get(i).getBehavioralHabit());
            systemTaskAdd.setTaskStructure(sysTasks.get(i).getTaskStructure());
            systemTaskAdd.setDifficulty(sysTasks.get(i).getDifficulty());
            systemTaskAdd.setAgeRang(sysTasks.get(i).getAgeRang());
            systemTaskAdd.setMainTerritory(sysTasks.get(i).getMainTerritory());
            systemTaskAdd.setChildTerritory(sysTasks.get(i).getChildTerritory());
            systemTaskAdd.setTarget1(sysTasks.get(i).getTarget1());
            systemTaskAdd.setTarget2(sysTasks.get(i).getTarget2());
            systemTaskAdd.setSkill(sysTasks.get(i).getSkill());
            systemTaskAdd.setPerceive(sysTasks.get(i).getPerceive());
            systemTaskAdd.setEmotion(sysTasks.get(i).getEmotion());
            systemTaskAdd.setOrganizational(sysTasks.get(i).getOrganizational());
            systemTaskAdd.setPublishId(publishServerBack.getPublishId());
            RI addTask = addTask(systemTaskAdd);
            if (addTask == null || addTask.getResultCode() != OK) {
                String msg = "第" + (i + 1) + "行添加系统时出错，任务名称为:" + sysTasks.get(i).getTaskName() + "\n";
                errorMsg.append(msg);
            }
        }
        if (errorMsg.length() > 1) {
            throw new HyyException(500, errorMsg.toString());
        }
    }

    private RI addTask(SystemTaskAdd systemTaskAdd) {
        String url = WS + "web/systemTask/taskAdd";
        String resp;
        try {
            resp = HttpsUtils.post(url, JSON.toJSONString(systemTaskAdd));
        } catch (Exception e) {
            return null;
        }
        RS rs = JSON.parseObject(resp, RS.class);
        if (rs.getResultCode() != OK) {
            return null;
        }
        return rs;
    }

    private RI publishImageEnd(String imageToken, Integer imageId) {
        String url = WS + "xb/app/publishImageEnd";
        String resp;
        Map<String, String> params = new HashMap<>();
        params.put("token", FinalStr.WEB_TOKEN);
        params.put("imageToken", imageToken);
        params.put("imageId", imageId.toString());
        try {
            resp = HttpsUtils.get(url, params);
        } catch (Exception e) {
            return null;
        }
        RS rs = JSON.parseObject(resp, RS.class);
        if (rs.getResultCode() != OK) {
            return null;
        }
        return rs;
    }

    private PublishImageServerBackRSD publishImageData(PublishImageData publishImageData) {
        String url = WS + "xb/app/publishImageData";
        String resp;
        try {
            resp = HttpsUtils.post(url, JSON.toJSONString(publishImageData));
        } catch (Exception e) {
            return null;
        }
        PublishImageServerBackRSD rsd = JSON.parseObject(resp, PublishImageServerBackRSD.class);
        if (rsd.getResultCode() != OK) {
            return null;
        }
        return rsd;
    }

    private RI publishVideoDataEnd(String publishToken, Integer publishId) {
        String url = WS + "xb/app/publishVideoEnd";
        String resp;
        Map<String, String> params = new HashMap<>();
        params.put("token", FinalStr.WEB_TOKEN);
        params.put("publishToken", publishToken);
        params.put("publishId", publishId.toString());
        try {
            resp = HttpsUtils.get(url, params);
        } catch (Exception e) {
            return null;
        }
        RS rs = JSON.parseObject(resp, RS.class);
        if (rs.getResultCode() != OK) {
            return null;
        }
        return rs;
    }

    public PublishServerBackRSD publishVideoData(PublishVideoDataPost publishVideoDataPost) {
        String url = WS + "xb/app/publishVideo";
        String resp;
        try {
            resp = HttpsUtils.post(url, JSON.toJSONString(publishVideoDataPost));
        } catch (Exception e) {
            return null;
        }
        return JSON.parseObject(resp, PublishServerBackRSD.class);
    }


    public ClassifyList getClassifyList() {
        String url = WS + "web/systemTask/classifyList";
        String resp;
        try {
            resp = HttpsUtils.get(url, new HashMap<>());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        ClassifyListRSD rsd = JSON.parseObject(resp, ClassifyListRSD.class);
        if (rsd.getResultCode() != OK) {
            return null;
        }
        return rsd.getData();
    }

    public void checkExcelHead(List<String[]> strings) {
        if (!PermissionOperation.TASK_NAME.equals(strings.get(0)[0])) {
            throw new HyyException(500, "任务名称表头不对");
        }
        if (!PermissionOperation.TASK_MATERIALS.equals(strings.get(0)[1])) {
            throw new HyyException(500, "任务材料表头不对");
        }
        if (!PermissionOperation.TASK_DES.equals(strings.get(0)[2])) {
            throw new HyyException(500, "任务描述表头不对");
        }
        if (!PermissionOperation.TASK_EXP.equals(strings.get(0)[3])) {
            throw new HyyException(500, "关键经验表头不对");
        }
        if (!PermissionOperation.EXP_DES.equals(strings.get(0)[4])) {
            throw new HyyException(500, "关键经验描述表头不对");
        }
        if (!PermissionOperation.HABIT.equals(strings.get(0)[5])) {
            throw new HyyException(500, "行为习惯表头不对");
        }
        if (!PermissionOperation.DIFFICULTY.equals(strings.get(0)[6])) {
            throw new HyyException(500, "游戏指数表头不对");
        }
        if (!PermissionOperation.STRUCT.equals(strings.get(0)[7])) {
            throw new HyyException(500, "任务结构表头不对");
        }
        if (!PermissionOperation.AGE.equals(strings.get(0)[8])) {
            throw new HyyException(500, "使用年龄段表头不对");
        }
        if (!PermissionOperation.MAIN_FIELD.equals(strings.get(0)[9])) {
            throw new HyyException(500, "主要领域表头不对");
        }
        if (!PermissionOperation.CHILD_FILED.equals(strings.get(0)[10])) {
            throw new HyyException(500, "子领域表头不对");
        }
        if (!PermissionOperation.TARGET1.equals(strings.get(0)[11])) {
            throw new HyyException(500, "发展目标1表头不对");
        }
        if (!PermissionOperation.TARGET2.equals(strings.get(0)[12])) {
            throw new HyyException(500, "发展目标2表头不对");
        }
        if (!PermissionOperation.PERCEIVE.equals(strings.get(0)[13])) {
            throw new HyyException(500, "认知表头不对");
        }
        if (!PermissionOperation.EMOTION.equals(strings.get(0)[14])) {
            throw new HyyException(500, "情感表头不对");
        }
        if (!PermissionOperation.SKILL.equals(strings.get(0)[15])) {
            throw new HyyException(500, "技能表头不对");
        }
        if (!PermissionOperation.ORGANIZATION.equals(strings.get(0)[16])) {
            throw new HyyException(500, "组织形式表头不对");
        }
        if (!PermissionOperation.VIDEO_URL.equals(strings.get(0)[17])) {
            throw new HyyException(500, "视频地址表头不对");
        }
    }

    public List<SysTaskHead> readAndCheck(List<String[]> strings) {
        List<SysTaskHead> sysTasks = new ArrayList<>();
        for (int i = 1; i < strings.size(); i++) {
            SysTaskHead sysTask = new SysTaskHead();
            sysTask.setTaskName(strings.get(i)[0]);
            sysTask.setTaskMaterials(strings.get(i)[1]);
            sysTask.setTaskDes(strings.get(i)[2]);
            sysTask.setKeyExperience(strings.get(i)[3]);
            sysTask.setKeyExperienceDes(strings.get(i)[4]);
            Integer habit = checkHabit(strings.get(i)[5], i);
            sysTask.setBehavioralHabit(habit);
            Integer difficulty = checkDifficulty(strings.get(i)[6], i);
            sysTask.setDifficulty(difficulty);
            Integer struct = checkStruct(strings.get(i)[7], i);
            sysTask.setTaskStructure(struct);
            Integer age = checkAge(strings.get(i)[8], i);
            sysTask.setAgeRang(age);
            Integer[] filed = checkFiled(strings.get(i)[9], strings.get(i)[10], i);
            sysTask.setMainTerritory(filed[0]);
            sysTask.setChildTerritory(filed[1]);
            Integer target1 = checkTarget1(strings.get(i)[11], i);
            sysTask.setTarget1(target1);
            Integer target2 = checkTarget2(strings.get(i)[12], i);
            sysTask.setTarget2(target2);
            Integer perceive = checkPerceive(strings.get(i)[13], i);
            sysTask.setPerceive(perceive);
            Integer emotion = checkEmotion(strings.get(i)[14], i);
            sysTask.setEmotion(emotion);
            Integer skill = checkSkill(strings.get(i)[15], i);
            sysTask.setSkill(skill);
            Integer organization = checkOrganization(strings.get(i)[16], i);
            sysTask.setOrganizational(organization);
            String path = checkFile(strings.get(i)[17], i);
            sysTask.setPath(path);
            sysTasks.add(sysTask);
        }
        return sysTasks;
    }

    public Integer checkHabit(String content, Integer index) {
        List<NormalDict> habit = classifyList.getBehavioralHabit();
        for (NormalDict normalDict : habit) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        return null;
    }

    public Integer checkDifficulty(String content, Integer index) {
        List<NormalDict> difficulty = classifyList.getDifficulty();
        for (NormalDict normalDict : difficulty) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，游戏指数 数据字典有误");

    }

    public Integer checkStruct(String content, Integer index) {
        List<NormalDict> taskStructure = classifyList.getTaskStructure();
        for (NormalDict normalDict : taskStructure) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，任务结构 数据字典有误");

    }

    public Integer checkAge(String content, Integer index) {
        List<NormalDict> ageRang = classifyList.getAgeRang();
        for (NormalDict normalDict : ageRang) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，年龄段 数据字典有误");
    }

    public Integer[] checkFiled(String content, String childContent, Integer index) {
        List<TreeDict> mainTerritory = classifyList.getMainTerritory();
        for (TreeDict treeDict : mainTerritory) {
            if (treeDict.getTerritoryName().equals(content)) {
                for (ChildDict childTerritory : treeDict.getChildTerritories()) {
                    if (childTerritory.getTerritoryName().equals(childContent)) {
                        return new Integer[]{treeDict.getTerritoryId(), childTerritory.getTerritoryId()};
                    }
                }
                throw new HyyException(500, "第" + (index + 1) + "行，子领域 数据字典有误");
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，主领域 数据字典有误");
    }

    public Integer checkTarget1(String content, Integer index) {
        List<NormalDict> target1 = classifyList.getTarget1();
        for (NormalDict normalDict : target1) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，发展目标1 数据字典有误");
    }

    public Integer checkTarget2(String content, Integer index) {
        List<NormalDict> target2 = classifyList.getTarget2();
        for (NormalDict normalDict : target2) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，发展目标2 数据字典有误");
    }

    public Integer checkPerceive(String content, Integer index) {
        List<NormalDict> perceive = classifyList.getPerceive();
        for (NormalDict normalDict : perceive) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，认知 数据字典有误");
    }

    public Integer checkEmotion(String content, Integer index) {
        List<NormalDict> emotion = classifyList.getEmotion();
        for (NormalDict normalDict : emotion) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，情感 数据字典有误");
    }

    public Integer checkSkill(String content, Integer index) {
        List<NormalDict> skill = classifyList.getSkill();
        for (NormalDict normalDict : skill) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，技能 数据字典有误");
    }

    public Integer checkOrganization(String content, Integer index) {
        List<NormalDict> organizational = classifyList.getOrganizational();
        for (NormalDict normalDict : organizational) {
            if (normalDict.getName().equals(content)) {
                return normalDict.getId();
            }
        }
        throw new HyyException(500, "第" + (index + 1) + "行，组织形式 数据字典有误");
    }

    public String checkFile(String path, Integer index) {
        if (!path.endsWith(".mp4")) {
            throw new HyyException(500, "第" + (index + 1) + "行，视频地址有误 只能为mp4文件");
        }
        File file = new File(path);
        if (!file.exists()) {
            throw new HyyException(500, "第" + (index + 1) + "行，视频地址有误 文件不存在");
        }
        if (file.length() < 10 * 1024) {
            throw new HyyException(500, "第" + (index + 1) + "行，视频小于10K，请检查视频文件");
        }
        return path;
    }
}
